/*
* Autopsy Forensic Browser
*
* Copyright 2016 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.imagegallery.gui;
import java.lang.reflect.InvocationTargetException;
import java.util.Comparator;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javax.swing.SortOrder;
import org.sleuthkit.autopsy.imagegallery.FXMLConstructor;
/**
*
*/
public class SortChooser<X, Y extends Comparator<X>> extends HBox {
@FXML
private RadioButton ascRadio;
@FXML
private RadioButton descRadio;
@FXML
private ToggleGroup orderGroup;
@FXML
private ComboBox<Y> sortByBox;
private final ObservableList<Y> comparators;
private final ReadOnlyObjectWrapper<SortOrder> sortOrder = new ReadOnlyObjectWrapper<>(SortOrder.ASCENDING);
private final SimpleBooleanProperty sortOrderDisabled = new SimpleBooleanProperty(false);
private final SimpleObjectProperty<ValueType> valueType = new SimpleObjectProperty<>(ValueType.NUMERIC);
public SortChooser(ObservableList<Y> comps) {
this.comparators = comps;
FXMLConstructor.construct(this, "SortChooser.fxml");
}
@FXML
void initialize() {
assert ascRadio != null : "fx:id=\"ascRadio\" was not injected: check your FXML file 'Toolbar.fxml'.";
assert descRadio != null : "fx:id=\"descRadio\" was not injected: check your FXML file 'Toolbar.fxml'.";
assert orderGroup != null : "fx:id=\"orderGroup\" was not injected: check your FXML file 'Toolbar.fxml'.";
assert sortByBox != null : "fx:id=\"sortByBox\" was not injected: check your FXML file 'Toolbar.fxml'.";
ascRadio.getStyleClass().remove("radio-button");
ascRadio.getStyleClass().add("toggle-button");
descRadio.getStyleClass().remove("radio-button");
descRadio.getStyleClass().add("toggle-button");
valueType.addListener((observable, oldValue, newValue) -> {
ascRadio.setGraphic(new ImageView(newValue.getAscendingImage()));
descRadio.setGraphic(new ImageView(newValue.getDescendingImage()));
});
ascRadio.disableProperty().bind(sortOrderDisabled);
descRadio.disableProperty().bind(sortOrderDisabled);
ascRadio.selectedProperty().addListener(selectedToggle -> {
sortOrder.set(orderGroup.getSelectedToggle() == ascRadio ? SortOrder.ASCENDING : SortOrder.DESCENDING);
});
sortByBox.setItems(comparators);
sortByBox.setCellFactory(listView -> new ComparatorCell());
sortByBox.setButtonCell(new ComparatorCell());
}
public ValueType getValueType() {
return valueType.get();
}
public void setValueType(ValueType type) {
valueType.set(type);
}
public SimpleObjectProperty<ValueType> valueTypeProperty() {
return valueType;
}
public void setSortOrderDisabled(boolean disabled) {
sortOrderDisabled.set(disabled);
}
public boolean isSortOrderDisabled() {
return sortOrderDisabled.get();
}
public SimpleBooleanProperty sortOrderDisabledProperty() {
return sortOrderDisabled;
}
public SortOrder getSortOrder() {
return sortOrder.get();
}
public ReadOnlyObjectProperty<SortOrder> sortOrderProperty() {
return sortOrder.getReadOnlyProperty();
}
public Y getComparator() {
return sortByBox.getSelectionModel().getSelectedItem();
}
public void setComparator(Y selected) {
sortByBox.getSelectionModel().select(selected);
}
public ReadOnlyObjectProperty<Y> comparatorProperty() {
return sortByBox.getSelectionModel().selectedItemProperty();
}
public enum ValueType {
LEXICOGRAPHIC("sort_asc_az.png", "sort_desc_az.png"),
NUMERIC("sort_ascending.png", "sort_descending.png");
private final Image ascImage;
private final Image descImage;
private ValueType(String ascImageName, String descImageName) {
this.ascImage = new Image("/org/sleuthkit/autopsy/imagegallery/images/" + ascImageName);
this.descImage = new Image("/org/sleuthkit/autopsy/imagegallery/images/" + descImageName);
}
private Image getAscendingImage() {
return ascImage;
}
private Image getDescendingImage() {
return descImage;
}
}
private class ComparatorCell extends ListCell<Y> {
@Override
protected void updateItem(Y item, boolean empty) {
super.updateItem(item, empty); //To change body of generated methods, choose Tools | Templates.
if (empty || null == item) {
setText(null);
setGraphic(null);
} else {
try {
String displayName = (String) item.getClass().getMethod("getDisplayName").invoke(item);
setText(displayName);
Image icon = (Image) item.getClass().getMethod("getIcon").invoke(item);
setGraphic(new ImageView(icon));
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
// Exceptions.printStackTrace(ex);
setText(item.toString());
setGraphic(null);
}
}
}
}
}